import { create } from "zustand";
import { safeJsonParse, safeJsonStringify } from '../utils';

interface UserInfo {
  /** 用户id */
  id: string;
  /** 姓名 */
  name: string;
  /** 手机号 */
  phone: string;
}

interface Status {
  /** 是否正在加载 */
  loading: boolean;
}

/** 持久化name */
const storageKey = "GlobalUserInfo";

function getDefault() {
  return {
    id: "001",
    name: "Admin",
    phone: "18888888888",
  };
}

/**
 * 用户信息Store
 */
const userInfoStore = create<UserInfo>(() => {
  const valueStr = localStorage.getItem(storageKey);
  return valueStr ? safeJsonParse(valueStr, getDefault()): getDefault();
});

/**
 * 用户信息加载信息
 */
const userInfoStatusStore = create<Status>(() => ({ loading: false }));

/** 变更订阅, 持久化 */
userInfoStore.subscribe((state, _) => {
  const str = safeJsonStringify(state);
  if (str !== undefined)
    localStorage.setItem(storageKey, str);
});

/**
 * 更新用户信息
 */
function updateUserInfo(data: Partial<UserInfo>) {
  userInfoStore.setState(data);
}

/**
 * 更新用户信息状态
 */
function updateUserInfoStatus(data: Partial<Status>) {
  userInfoStatusStore.setState(data);
}

/**
 * 重置用户信息
 */
function resetUserInfo() {
  updateUserInfo(getDefault());
  updateUserInfoStatus({ loading: false });
}

/**
 * 从接口更新用户信息
 */
async function loadUserInfo() {
  updateUserInfoStatus({ loading: true });
  const res = await new Promise<{ success: boolean; data: UserInfo }>((resolve) => {
    setTimeout(() => {
      resolve({
        success: true,
        data: {
          id: Date.now().toString().slice(8),
          name: Math.random().toString(36).substring(2),
          phone: Date.now().toString().slice(0, 11),
        },
      });
    }, 2000);
  });
  if (res.success) {
    updateUserInfo(res.data);
    updateUserInfoStatus({ loading: false });
  }
}

/**
 * 用户信息管理hook(包含读取/更新/重置/加载)
 * @example const { userInfo, loading, loadUserInfo } = useUserInfo();
 */
export function useUserInfo() {
  const userInfo = userInfoStore();
  const userInfoStatus = userInfoStatusStore();
  return {
    // 这里赋值boolean类型后, 后续还能更新, (数据改变会导致函数被重新执行?)
    loading: userInfoStatus.loading,
    userInfo,
    updateUserInfo,
    resetUserInfo,
    loadUserInfo,
  };
}
